package com.ly.heart.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.annotation.DataScope;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.core.domain.entity.SysUser;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.MessageConstants;
import com.ly.common.utils.erp.ReturnPage;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.CheckSaleMarkedPriceDto;
import com.ly.heart.domain.dto.SaleOrderAddDto;
import com.ly.heart.domain.dto.SaleOrderQueryDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.heart.domain.vo.*;
import com.ly.heart.service.*;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import com.ly.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import com.ly.heart.mapper.SaleOrderMapper;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

/**
 * 销售订单Service业务层处理
 * @author wutao
 * @date 2024-06-26
 */
@Service
public class SaleOrderServiceImpl extends ServiceImpl<SaleOrderMapper, SaleOrderEntity> implements ISaleOrderService {

    @Resource
    private SaleOrderMapper saleOrderMapper;
    @Resource
    private IActModelService actModelService;
    @Resource
    private IContractSaleService contractSaleService;
    @Resource
    private IMaterialDetailService materialDetailService;
    @Resource
    private IMaterialService materialInfoService;
    @Resource
    private IContractOrderService contractOrderService;
    @Resource
    private ISaleMarkedPriceService markedPriceService;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private IOrderPurchaseTermsService orderPurchaseTermsService;
    @Resource
    private ISaleOrderLogisticsService saleOrderLogisticsService;
    @Resource
    private ISaleOrderDeliveryService saleOrderDeliveryService;
    @Resource
    private ISaleOrderDeliveryDetailService saleOrderDeliveryDetailService;
    @Resource
    private ISaleCollectionPlanService saleCollectionPlanService;
    @Resource
    private ISaleQuotationService saleQuotationService;
    @Resource
    private ISaleAndQuotationService saleAndQuotationService;
    @Resource
    private IKingDocTypeService kingDocTypeEntityService;
    @Resource
    private ICustomerService customerInfoService;
    @Resource
    private IOrderService orderService;
    @Resource
    private IActTaskCommentService actTaskCommentService;
    @Resource
    private IActModelService iActModelService;
    @Resource
    private IKingBaseReceiptPayConditionService kingBaseReceiptConditionEntityService;
    @Resource
    private IKingBaseCurrencyService kingBaseCurrencyEntityService;
    @Resource
    private IKingBaseSettlementTypeService iKingBaseSettlementTypeService;
    @Resource
    private IMaterialService iMaterialService;
    @Resource
    private IKingBaseMeteringUnitService iKingBaseMeteringUnitService;


    @Override
    @DataScope(deptAlias = "sd")
    public IPage<SaleOrderDetailVo> selectSaleOrderDetailList (SaleOrderQueryDto saleOrderQueryDto) {

        return saleOrderMapper.selectSaleOrderDetailList ( saleOrderQueryDto );
    }


    @Override
    public IPage<SaleOrderDetailVo> selectSaleOrderDetailListNew (SaleOrderQueryDto saleOrderQueryDto) {
        IPage<SaleOrderDetailVo> saleOrderDetailVoIPage = saleOrderMapper.selectSaleOrderDetailListNew ( saleOrderQueryDto );
        saleOrderDetailVoIPage.getRecords ().forEach ( s -> {
            //审批人信息
            ActTaskCommentEntity actTaskComment = actTaskCommentService.queryLastComment ( s.getInstanceId () );
            Optional.ofNullable ( actTaskComment ).ifPresent ( taskComment -> {
                s.setApprovedUser ( taskComment.getApprovedUser () );
                s.setRemark ( taskComment.getRemark () );
            } );
            ActCurrentTaskVo currentTaskVo = iActModelService.getCurrentTaskByInstanceId ( s.getInstanceId () );
            Optional.ofNullable ( currentTaskVo ).ifPresent ( currentTask -> {
                s.setCurrentTask ( currentTask );
            } );
        } );
        return saleOrderDetailVoIPage;
    }

    /**
     * 查询销售订单
     * @param id 销售订单ID
     * @return 销售订单
     */
    @Override
    public SaleOrderEntity selectSaleOrderById (String id) {
        SaleOrderEntity saleOrderEntity = this.getById ( id );
        //客户名称
        CustomerEntity customerEntity = customerInfoService.getById ( saleOrderEntity.getCustomerId () );
        Optional.ofNullable ( customerEntity ).ifPresent ( customer -> {
            saleOrderEntity.setCustomerName ( customer.getCustomerName () );
        } );
        //价目名称
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getPriceinfoId () ) ) {
            SaleMarkedPriceEntity priceEntity = markedPriceService.getById ( saleOrderEntity.getPriceinfoId () );
            Optional.ofNullable ( priceEntity ).ifPresent ( price -> {
                saleOrderEntity.setPriceInfoName ( price.getMarkedPriceName () );
            } );
        }
        //销售部门
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getSaleDept () ) ) {
            SysDept saleDept = sysDeptService.getById ( saleOrderEntity.getSaleDept () );
            Optional.ofNullable ( saleDept ).ifPresent ( dept -> {
                saleOrderEntity.setSaleDeptName ( dept.getDeptName () );
            } );
        }
        //销售员名字
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getSaleId () ) ) {
            SysUser sysUser = sysUserService.getById ( saleOrderEntity.getSaleId () );
            Optional.ofNullable ( sysUser ).ifPresent ( user -> {
                saleOrderEntity.setSalePersonName ( user.getNickName () );
            } );
        }
        //收款条件名称
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getPaymentTerms () ) ) {
            KingBaseReceiptPayConditionEntity kingBaseReceiptPayConditionEntity = kingBaseReceiptConditionEntityService.getById ( saleOrderEntity.getPaymentTerms () );
            Optional.ofNullable ( kingBaseReceiptPayConditionEntity ).ifPresent ( kingBaseReceiptPayCondition -> {
                saleOrderEntity.setPaymentTermsName ( kingBaseReceiptPayCondition.getTitle () );
            } );
        }
        //结算货币
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getCurrency () ) ) {
            KingBaseCurrencyEntity kingBaseCurrencyEntity = kingBaseCurrencyEntityService.getOne ( new LambdaQueryWrapper<> ( KingBaseCurrencyEntity.class ).eq ( KingBaseCurrencyEntity :: getCode, saleOrderEntity.getCurrency () ) );
            Optional.ofNullable ( kingBaseCurrencyEntity ).ifPresent ( kingBaseCurrency -> {
                saleOrderEntity.setSettleCurrencyName ( kingBaseCurrency.getCurrencyName () );
            } );
        }
        //结算方式
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getSettlementType () ) ) {
            KingBaseSettlementTypeEntity settlementTypeEntity = iKingBaseSettlementTypeService.getOne ( new LambdaQueryWrapper<KingBaseSettlementTypeEntity> ().eq ( KingBaseSettlementTypeEntity :: getId, saleOrderEntity.getSettlementType () ) );
            Optional.ofNullable ( settlementTypeEntity ).ifPresent ( type -> {
                saleOrderEntity.setSettlementTypeName ( type.getTitle () );
            } );
        }
        List<MaterialDetailEntity> list = materialDetailService.list ( new LambdaQueryWrapper<> ( MaterialDetailEntity.class )
                                                                               .eq ( MaterialDetailEntity :: getRelationId, id )
                                                                               .eq ( MaterialDetailEntity :: getType, ConstUtil.ORDER_SALE )
        );
        list.forEach ( detail -> {
            //物料名称
            if ( StringUtils.isNotEmpty ( detail.getMaterialCode () ) ) {
                MaterialEntity one = iMaterialService.getOne ( new LambdaQueryWrapper<MaterialEntity> ().eq ( MaterialEntity :: getMaterialCode, detail.getMaterialCode () ) );
                Optional.ofNullable ( one ).ifPresent ( materialEntity -> {
                    detail.setMaterialName ( materialEntity.getMaterialName () );
                } );
            }
            //单位
            if ( StringUtils.isNotEmpty ( detail.getPricingUnit () ) ) {
                KingBaseMeteringUnitEntity one = iKingBaseMeteringUnitService.getOne ( new LambdaQueryWrapper<KingBaseMeteringUnitEntity> ().eq ( KingBaseMeteringUnitEntity :: getMeteringUnitCode, detail.getPricingUnit () ) );
                Optional.ofNullable ( one ).ifPresent ( unitEntity -> {
                    detail.setPricingUnitName ( unitEntity.getMeteringUnitName () );
                } );
            }
        } );
        saleOrderEntity.setMaterialDetailEntities ( list );

        List<OrderPurchaseTermsEntity> purchaseTermsEntities = orderPurchaseTermsService.list ( new LambdaQueryWrapper<> ( OrderPurchaseTermsEntity.class ).eq ( OrderPurchaseTermsEntity :: getOrderId, id ) );
        saleOrderEntity.setOrderPurchaseTerms ( purchaseTermsEntities );

        List<SaleOrderLogisticsEntity> orderLogisticsEntities = saleOrderLogisticsService.list ( new LambdaQueryWrapper<> ( SaleOrderLogisticsEntity.class ).eq ( SaleOrderLogisticsEntity :: getOrderId, id ) );
        saleOrderEntity.setSaleOrderLogisticsEntities ( orderLogisticsEntities );

        List<SaleCollectionPlanEntity> collectionPlanEntities = saleCollectionPlanService.list ( new LambdaQueryWrapper<> ( SaleCollectionPlanEntity.class ).eq ( SaleCollectionPlanEntity :: getOrderId, id ) );
        saleOrderEntity.setSaleCollectionPlanEntities ( collectionPlanEntities );
        return saleOrderEntity;
    }

    /**
     * 查询销售订单列表
     * @param saleOrder 销售订单
     * @return 销售订单
     */
    @Override
    public List<SaleOrderEntity> selectSaleOrderList (SaleOrderEntity saleOrder) {
        return saleOrderMapper.selectSaleOrderList ( saleOrder );
    }


    /**
     * 暂存销售订单
     * @param saleOrderAddDto
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class)
    public AjaxResult draft (SaleOrderAddDto saleOrderAddDto) {
        boolean save = false;
        Date nowDate = DateUtils.getNowDate ();
        SaleOrderEntity saleOrderEntity = saleOrderAddDto.getSaleOrderEntity ();
        saleOrderEntity.setCreateTime ( nowDate );
        saleOrderEntity.setCreateBy ( SecurityUtils.getUsername () );
        saleOrderEntity.setState ( ConstUtil.STATE_IN_DRAFT );
        if ( StringUtils.isEmpty ( saleOrderEntity.getSaleCode () ) ) {
            String companyId = CurrentUserUtil.getCompanyId ();
            SysDept sysDept = sysDeptService.getById ( companyId );
            int count = this.count ();
            String countStr = String.format ( "%06d", count );
            String firstLetter = ChineseToPinyin.getFirstLetter ( sysDept.getDeptName () );
            String orderNumber = firstLetter.concat ( "_XSDD_" ).concat ( countStr );
            saleOrderEntity.setSaleCode ( orderNumber );
        }

        if ( StringUtils.isEmpty ( saleOrderAddDto.getSaleOrderEntity ().getId () ) ) {
            String tenderId = SnowflakeIdWorker.getInstance ().nextStringId ();
            saleOrderEntity.setCreateTime ( nowDate );
            saleOrderEntity.setCreateBy ( SecurityUtils.getUsername () );
            saleOrderEntity.setId ( tenderId );
            saleOrderEntity.setState ( ConstUtil.STATE_IN_DRAFT );
            this.saveDraftSaleOrderDetail ( saleOrderAddDto );
            save = this.save ( saleOrderEntity );
        } else {
            save = this.updateDraftSaleOrder ( saleOrderAddDto );
        }
        if ( ! save ) {
            return AjaxResult.error ( "暂存销售订单失败" );
        }
        return AjaxResult.success ( "暂存销售订单成功", saleOrderEntity.getId () );
    }

    /**
     * 提交销售订单
     * @param saleOrderAddDto
     * @return
     */
    @Override
    public AjaxResult submit (SaleOrderAddDto saleOrderAddDto) {
        SaleOrderEntity saleOrderEntity = saleOrderAddDto.getSaleOrderEntity ();
        if ( StringUtils.isEmpty ( saleOrderEntity.getId () ) ) {
            return AjaxResult.error ( "请先暂存单据" );
        }
        AjaxResult ajaxResult = this.insertSaleOrder ( saleOrderAddDto );
        return ajaxResult;
    }

    /**
     * 查询销售订单推送金蝶
     * @param id
     * @return
     */
    @Override
    public SaleOrderCodeVo getSaleCodeById ( String id) {
        SaleOrderCodeVo saleOrderKingVo = saleOrderMapper.getSaleCodeById ( id );
        return saleOrderKingVo;
    }


    /**
     * 新增销售订单
     * 选单分：销售合同，报价单
     * @param saleOrderAddDto 销售订单
     * @return 结果
     */
//    @Override
    private AjaxResult insertSaleOrder (SaleOrderAddDto saleOrderAddDto) {
        Date nowDate = DateUtils.getNowDate ();
        SaleOrderEntity saleOrderEntity = saleOrderAddDto.getSaleOrderEntity ();
        String tenderId = saleOrderEntity.getId ();
        saleOrderEntity.setDeptId ( CurrentUserUtil.getCompanyId () );
        StartProcessDto startDto = new StartProcessDto ().setBusinessId ( tenderId ).setBusinessType ( saleOrderAddDto.getSaleOrderEntity ().getBusinessType () ).setModelId ( saleOrderAddDto.getSaleOrderEntity ().getModelId () )
                .setBusinessName ( "销售订单_".concat ( tenderId ) );
        String instanceId = actModelService.startProcess ( startDto );
        saleOrderEntity.setCreateTime ( nowDate );
        saleOrderEntity.setInstanceId ( instanceId );
        saleOrderEntity.setState ( ConstUtil.STATE_IN_PROCESS );

        if ( CollectionUtils.isEmpty ( saleOrderAddDto.getMaterialDetailEntities () ) ) {
            return AjaxResult.error ( "销售订单明细不能为空" );
        }
        //选择价目表了，但是没有满足价目表规定的价格需要单独审核
        List<String> relationIds = saleOrderAddDto.getMaterialDetailEntities ().stream ().distinct ().map ( MaterialDetailEntity :: getRelationId ).collect ( Collectors.toList () );
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getSourceDocType () ) ) {
            switch ( saleOrderEntity.getSourceDocType () ) {
                case ConstUtil.SALE_DOC_TYPE_CONTRACTS:
                    checkNumByContracts ( saleOrderAddDto.getMaterialDetailEntities (), relationIds );
                    break;
                case ConstUtil.SALE_DOC_TYPE_QUOTE:
                    //查询所有的报价单
                    checkNumBySaleQuotation ( saleOrderAddDto.getMaterialDetailEntities (), relationIds );
                    break;
            }
        }
        if ( StringUtils.isEmpty ( saleOrderEntity.getSaleCode () ) ) {
            String companyId = CurrentUserUtil.getCompanyId ();
            SysDept sysDept = sysDeptService.getById ( companyId );
            int count = this.count ();
            String countStr = String.format ( "%06d", count );
            String firstLetter = ChineseToPinyin.getFirstLetter ( sysDept.getDeptName () );
            String orderNumber = firstLetter.concat ( "_XSDD_" ).concat ( countStr );
            saleOrderEntity.setSaleCode ( orderNumber );
        }
        if ( StringUtils.isEmpty ( saleOrderEntity.getUnpaidAmount () ) ) {
            saleOrderEntity.setUnpaidAmount ( saleOrderEntity.getTotalTaxPrice () );
        }
        //新增销售订单明细
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getMaterialDetailEntities () ) ) {
            //先删除在添加
            boolean remove = materialDetailService.remove ( new LambdaQueryWrapper<> ( MaterialDetailEntity.class )
                                                                    .eq ( MaterialDetailEntity :: getRelationId, tenderId )
                                                                    .eq ( MaterialDetailEntity :: getType, ConstUtil.ORDER_SALE )
            );
            saleOrderAddDto.getMaterialDetailEntities ().forEach ( s -> {
                String id = SnowflakeIdWorker.getInstance ().nextStringId ();
                s.setId ( id );
                if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getCheckSaleOrderDetail () ) ) {
                    if ( saleOrderAddDto.getCheckSaleOrderDetail ().stream ().anyMatch ( m -> m.getMaterialCode ().equals ( s.getMaterialCode () ) ) ) {
                        s.setState ( "0" );
                        StartProcessDto detailStart = new StartProcessDto ().setBusinessId ( s.getId () ).setBusinessType ( s.getBusinessType () ).setModelId ( s.getModelId () )
                                .setBusinessName ( "销售订单明细_".concat ( s.getId () ) );
                        String checkInstanceId = actModelService.startProcess ( detailStart );
                        saleOrderEntity.setInstanceId ( checkInstanceId );
                    }
                }
                s.setRelationId ( saleOrderEntity.getId () );
                s.setType ( ConstUtil.ORDER_SALE );
                s.setCreateTime ( nowDate );
                materialDetailService.save ( s );
            } );
            for ( MaterialDetailEntity materialDetailEntity : saleOrderAddDto.getMaterialDetailEntities () ) {
                //销售订单交货明细基础信息，详情信息
                SaleOrderDeliveryEntity saleOrderDeliveryEntity = materialDetailEntity.getSaleOrderDelivery ();
                if ( ! ObjectUtils.isEmpty ( saleOrderDeliveryEntity ) ) {
                    //先删除在添加
                    List<SaleOrderDeliveryEntity> list = saleOrderDeliveryService.list ( new LambdaQueryWrapper<> ( SaleOrderDeliveryEntity.class ).eq ( SaleOrderDeliveryEntity :: getOrderId, tenderId ) );
                    if ( ! CollectionUtils.isEmpty ( list ) ) {
                        boolean removed = saleOrderDeliveryService.remove ( new LambdaQueryWrapper<> ( SaleOrderDeliveryEntity.class )
                                                                                    .eq ( SaleOrderDeliveryEntity :: getOrderId, tenderId ) );
                        List<String> deliveryIds = list.stream ().map ( s -> s.getId () ).collect ( Collectors.toList () );
                        boolean removeAll = saleOrderDeliveryDetailService.remove ( new LambdaQueryWrapper<> ( SaleOrderDeliveryDetailEntity.class ).in ( SaleOrderDeliveryDetailEntity :: getDeliveryId, deliveryIds ) );
                    }
                    String deliverId = SnowflakeIdWorker.getInstance ().nextStringId ();
                    saleOrderDeliveryEntity.setId ( deliverId );
                    saleOrderDeliveryEntity.setOrderId ( saleOrderEntity.getId () );
                    saleOrderDeliveryEntity.setCreateTime ( nowDate );
                    boolean save = saleOrderDeliveryService.save ( saleOrderDeliveryEntity );
                    if ( ! save ) {
                        return AjaxResult.error ( "新增交货明细基础信息失败" );
                    }
                    if ( ! CollectionUtils.isEmpty ( saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities () ) ) {
                        saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities ().forEach ( s -> {
                            s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                            s.setDeliveryId ( deliverId );
                            s.setCreateTime ( nowDate );
                        } );
                        boolean saveBatch = saleOrderDeliveryDetailService.saveBatch ( saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities () );
                        if ( ! saveBatch ) {
                            return AjaxResult.error ( "新增交货明细详情信息失败" );
                        }
                    }
                }
            }
        }
        //销售订单销售条款信息
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getOrderPurchaseTerms () ) ) {
            //先删除在添加
            boolean remove = orderPurchaseTermsService.remove ( new LambdaQueryWrapper<> ( OrderPurchaseTermsEntity.class ).eq ( OrderPurchaseTermsEntity :: getOrderId, saleOrderEntity.getId () ) );
            saleOrderAddDto.getOrderPurchaseTerms ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setOrderId ( saleOrderEntity.getId () );
                s.setType ( ConstUtil.SALE_ORDER_TYPE_TERMS );
                s.setCreateTime ( nowDate );
            } );
            boolean saveBatch = orderPurchaseTermsService.saveBatch ( saleOrderAddDto.getOrderPurchaseTerms () );
            if ( ! saveBatch ) {
                throw new RuntimeException ( "新增销售订单条款信息失败！" );
            }
        }
        //销售订单物流跟踪信息
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getSaleOrderLogisticsEntities () ) ) {
            //先删除在添加
            boolean remove = saleOrderLogisticsService.remove ( new LambdaQueryWrapper<> ( SaleOrderLogisticsEntity.class ).eq ( SaleOrderLogisticsEntity :: getOrderId, saleOrderEntity.getId () ) );
            saleOrderAddDto.getSaleOrderLogisticsEntities ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setOrderId ( saleOrderEntity.getId () );
                s.setCreateTime ( nowDate );
            } );
            boolean b = saleOrderLogisticsService.saveBatch ( saleOrderAddDto.getSaleOrderLogisticsEntities () );
            if ( ! b ) {
                return AjaxResult.error ( "新增销售订单物流信息失败" );
            }
        }
        //销售订单收款计划
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getSaleCollectionPlanEntities () ) ) {
            boolean remove = saleCollectionPlanService.remove ( new LambdaQueryWrapper<> ( SaleCollectionPlanEntity.class ).eq ( SaleCollectionPlanEntity :: getOrderId, saleOrderEntity.getId () ) );
            saleOrderAddDto.getSaleCollectionPlanEntities ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setOrderId ( saleOrderEntity.getId () );
                s.setCreateTime ( nowDate );
            } );
            boolean saveBatch = saleCollectionPlanService.saveBatch ( saleOrderAddDto.getSaleCollectionPlanEntities () );
            if ( ! saveBatch ) {
                return AjaxResult.error ( "新增销售订单收款计划失败" );
            }
        }
        boolean save = this.updateById ( saleOrderEntity );
        if ( save ) {
            //插入合同关联关系
            if ( saleOrderEntity.getSourceDocType ().equals ( ConstUtil.SALE_DOC_TYPE_CONTRACTS ) ) {
                if ( ! CollectionUtils.isEmpty ( relationIds ) ) {
                    relationIds.forEach ( contrcatId -> {
                        ContractOrderEntity contractOrder = new ContractOrderEntity ();
                        contractOrder.setContractId ( contrcatId );
                        contractOrder.setSourceContractType ( ConstUtil.CONTRACT_SALE_TYPE );
                        contractOrder.setOrderId ( tenderId );
                        contractOrder.setSourceOrderType ( ConstUtil.ORDER_SALE_TYPE );
                        contractOrder.setCreateTime ( nowDate );
                        contractOrderService.save ( contractOrder );
                    } );
                }
            }
            if ( saleOrderEntity.getSourceDocType ().equals ( ConstUtil.SALE_DOC_TYPE_QUOTE ) ) {
                if ( ! CollectionUtils.isEmpty ( relationIds ) ) {
                    relationIds.forEach ( s -> {
                        SaleAndQuotationEntity saleAndQuotationEntity = new SaleAndQuotationEntity ();
                        saleAndQuotationEntity.setSaleOrderId ( tenderId );
                        saleAndQuotationEntity.setQuotationId ( s );
                        saleAndQuotationEntity.setCreateTime ( nowDate );
                        saleAndQuotationService.save ( saleAndQuotationEntity );

                    } );
                }

            }
            return AjaxResult.success ( MessageConstants.ADD_SUCCESS );
        } else {
            return AjaxResult.error ( MessageConstants.ADD_FAIL );
        }

    }

    /**
     * todo 如果选单类型是销售合同
     * 根据销售合同id查询该合同下的所有物料明细
     * @param orderDetails 销售订单明细，选择的是销售合同中的明细
     */
    private void checkNumByContracts (List<MaterialDetailEntity> orderDetails, List<String> relationIds) {
        if ( ! CollectionUtils.isEmpty ( orderDetails ) ) {

            //已选合同的所有销售合同明细
            List<MaterialDetailEntity> detailEntityList = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                               .in ( MaterialDetailEntity :: getRelationId, relationIds )
                                                                                               .eq ( MaterialDetailEntity :: getType, ConstUtil.CONTRACT_SALE_MATERIAL_TYPE )
                                                                                               .eq ( MaterialDetailEntity :: getIsUsed, ConstUtil.IS_USED_YES )
            );
            //查询所有的销售合同
            List<ContractSaleEntity> contractSaleEntities = contractSaleService.listByIds ( relationIds );
            //选择的多合同必须操作同一个客户
            if ( ! CollectionUtils.isEmpty ( relationIds ) && relationIds.size () > 1 ) {
                //过滤出销售订单里的客户
                List<ContractSaleEntity> contractProcureList = contractSaleService.list ( new QueryWrapper<ContractSaleEntity> ().in ( "id", relationIds ) );
                Set<String> customerIdsSet = contractProcureList.stream ()
                        .filter ( Objects :: nonNull )
                        .map ( ContractSaleEntity :: getCustomerId )
                        .collect ( Collectors.toCollection ( HashSet :: new ) );
                if ( customerIdsSet.size () > 1 ) {
                    // 构造更具体的异常信息
                    throw new RuntimeException ( "无法操作不同客户的单据" );
                }
            }
            //明细绑定合同的需判断，没有绑定合同的自定义新增的无需判断
            List<MaterialDetailEntity> detailEntities = orderDetails.stream ().filter ( s -> StringUtils.isNotEmpty ( s.getSourceRelationId () ) ).collect ( Collectors.toList () );
            detailEntities.forEach ( materialDetailEntity -> {
                ContractSaleEntity contractSaleEntity = contractSaleEntities.stream ().filter ( s -> s.getId ().equals ( materialDetailEntity.getRelationId () ) ).findFirst ().orElse ( null );
                switch ( contractSaleEntity.getSaleType () ) {
                    case ConstUtil.CONTRACT_SALE_TYPE_ORDINARY://普通合同
                        checkOrdinaryContract ( materialDetailEntity, contractSaleEntity, detailEntityList );
                        break;
                    case ConstUtil.CONTRACT_SALE_TYPE_AMOUNT://金额合同
                        checkAmountContract ( materialDetailEntity, contractSaleEntity, detailEntityList );
                        break;
                    case ConstUtil.CONTRACT_SALE_TYPE_MATERIAL:
                        break;
                    case ConstUtil.CONTRACT_SALE_TYPE_FRAMEWORK:
                        break;
                    default:
                        break;
                }
            } );


            List<List<MaterialDetailEntity>> materialSaleLists = new ArrayList<> ();
            for ( ContractSaleEntity contractSaleEntity : contractSaleEntities ) {
                // 根据合同ID查询关联的物料详情
                List<MaterialDetailEntity> list = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                       .eq ( MaterialDetailEntity :: getRelationId, contractSaleEntity.getId () )
                                                                                       .eq ( MaterialDetailEntity :: getType, ConstUtil.CONTRACT_SALE_MATERIAL_TYPE ) );
                if ( ! list.isEmpty () ) {
                    materialSaleLists.add ( list );
                }
            }
            // 通过合同ID集合批量查询需要关闭的合同
            Set<String> needCloseContractIds = new HashSet<> ();
            for ( List<MaterialDetailEntity> list : materialSaleLists ) {
                if ( list.stream ().allMatch ( s -> s.getExecuteStatus ().equals ( ConstUtil.MATERIAL_STATUS_FINISH ) ) ) {
                    needCloseContractIds.add ( list.get ( 0 ).getRelationId () );
                }
            }
            if ( ! needCloseContractIds.isEmpty () ) {
                List<ContractSaleEntity> contractSaleEntitiesToClose = contractSaleService.listByIds ( needCloseContractIds );
                for ( ContractSaleEntity contractSaleEntity : contractSaleEntitiesToClose ) {
                    contractSaleEntity.setIsClose ( ConstUtil.CONTRACT_IS_CLOSE_YES );
                    contractSaleService.updateById ( contractSaleEntity );
                }
            }

        }
    }

    /**
     * todo 如果选单类型是销售报价单
     * 根据销售合同id查询该合同下的所有物料明细
     * @param orderDetails
     */
    private void checkNumBySaleQuotation (List<MaterialDetailEntity> orderDetails, List<String> quotationIds) {
        if ( ! CollectionUtils.isEmpty ( orderDetails ) ) {
            List<SaleQuotationEntity> saleQuotationEntities = saleQuotationService.listByIds ( quotationIds );
            Set<String> collect = saleQuotationEntities.stream ()
                    .filter ( Objects :: nonNull )
                    .map ( SaleQuotationEntity :: getCustomerId )
                    .collect ( Collectors.toCollection ( HashSet :: new ) );
            if ( collect.size () > 1 ) {
                // 构造更具体的异常信息
                throw new RuntimeException ( "无法操作不同客户的单据" );
            }
            //查询所有的报价单明细
            List<MaterialDetailEntity> list = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                   .eq ( MaterialDetailEntity :: getRelationId, quotationIds )
                                                                                   .eq ( MaterialDetailEntity :: getType, ConstUtil.SALE_QUOTATION_MATERIAL_TYPE )
                                                                                   .eq ( MaterialDetailEntity :: getIsUsed, ConstUtil.IS_USED_YES )
            );
            //过滤出报价单明细还在执行中的
            List<MaterialDetailEntity> executeList = list.stream ().filter ( s -> s.getExecuteStatus ().equals ( ConstUtil.MATERIAL_STATUS_EXECUTE ) ).collect ( Collectors.toList () );

            if ( CollectionUtils.isEmpty ( executeList ) ) {
                throw new RuntimeException ( "已选报价单的物料已执行完毕" );
            }
            //判断多个报价单
            if ( quotationIds.size () > 1 ) {
                boolean hasEmptyQuotationId = list.stream ()
                        .collect ( Collectors.groupingBy ( MaterialDetailEntity :: getRelationId ) )
                        .values ()
                        .stream ()
                        .anyMatch ( Collection :: isEmpty );
                if ( hasEmptyQuotationId ) {
                    throw new RuntimeException ( "已选报价单的物料已执行完毕" );
                }
            }
            orderDetails.forEach ( materialDetailEntity -> {
                //查询此报价单中该物料的明细
                List<MaterialDetailEntity> detailEntities = list.stream ().filter ( s -> s.getMaterialId ().equals ( materialDetailEntity.getMaterialId () ) && s.getRelationId ().equals ( materialDetailEntity.getRelationId () ) ).collect ( Collectors.toList () );
                List<MaterialDetailEntity> materialExecuteList = detailEntities.stream ().filter ( s -> s.getExecuteStatus ().equals ( ConstUtil.MATERIAL_STATUS_EXECUTE ) ).collect ( Collectors.toList () );
                if ( CollectionUtils.isEmpty ( materialExecuteList ) ) {
                    throw new RuntimeException ( "该报价单的物料已执行完毕" );
                }
                //此报价单该物料还在执行中的明细数量总合
                double sum = materialExecuteList.stream ().mapToDouble ( execute -> Double.parseDouble ( execute.getNumber () ) ).sum ();
                if ( sum < Double.parseDouble ( materialDetailEntity.getNumber () ) ) {
                    throw new RuntimeException ( "已选的物料数量不能大于报价单物料数量" );
                }
                //查询此报价单已经执行过的订单
                List<SaleAndQuotationEntity> saleAndQuotationEntities = saleAndQuotationService.list ( new LambdaQueryWrapper<SaleAndQuotationEntity> ()
                                                                                                               .eq ( SaleAndQuotationEntity :: getQuotationId, materialDetailEntity.getRelationId () )
                                                                                                               .eq ( SaleAndQuotationEntity :: getIsUsed, ConstUtil.IS_USED_YES )
                );
                if ( CollectionUtils.isEmpty ( saleAndQuotationEntities ) ) {
                    //判断该报价单已经执行过的订单id
                    List<String> stringList = saleAndQuotationEntities.stream ().map ( s -> s.getSaleOrderId () ).collect ( Collectors.toList () );
                    if ( ! CollectionUtils.isEmpty ( stringList ) ) {
                        List<MaterialDetailEntity> materialDetailEntities = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                                                 .in ( MaterialDetailEntity :: getRelationId, stringList )
                                                                                                                 .eq ( MaterialDetailEntity :: getType, ConstUtil.ORDER_SALE )
                                                                                                                 .eq ( MaterialDetailEntity :: getIsUsed, ConstUtil.IS_USED_YES )
                                                                                                                 .eq ( MaterialDetailEntity :: getMaterialId, materialDetailEntity.getMaterialId () ) );
                        if ( ! CollectionUtils.isEmpty ( materialDetailEntities ) ) {
                            //此报价单已经已经执行过的此物料的订单明细的数量总合与金额总合
                            double excuteNum = materialDetailEntities.stream ().filter ( Objects :: nonNull ).mapToDouble ( detail -> Double.parseDouble ( detail.getNumber () ) ).sum ();
                            BigDecimal finshTotalAmount = materialDetailEntities.stream ()
                                    .map ( MaterialDetailEntity :: getAmountMoney )
                                    .map ( BigDecimal :: new )
                                    .reduce ( BigDecimal.ZERO, BigDecimal :: add );


                            double totalNum = detailEntities.stream ().filter ( Objects :: nonNull ).mapToDouble ( detail -> Double.parseDouble ( detail.getNumber () ) ).sum ();
                            BigDecimal totalAmount = detailEntities.stream ()
                                    .map ( MaterialDetailEntity :: getAmountMoney )
                                    .map ( BigDecimal :: new )
                                    .reduce ( BigDecimal.ZERO, BigDecimal :: add );
                            double surplusNum = totalNum - excuteNum;
                            BigDecimal surplusAmount = totalAmount.subtract ( finshTotalAmount );
                            BigDecimal amount = new BigDecimal ( materialDetailEntity.getAmountMoney () );
                            if ( Double.parseDouble ( materialDetailEntity.getNumber () ) > surplusNum || surplusAmount.compareTo ( amount ) == - 1 ) {
                                throw new RuntimeException ( "填写的该物料数量或金额不能大于该报价单的此物料数量或金额" );
                            }
                            if ( Double.parseDouble ( materialDetailEntity.getNumber () ) == surplusNum && amount.compareTo ( surplusAmount ) == 0 ) {
                                materialExecuteList.forEach ( s -> {
                                    materialDetailService.updateById ( s.setExecuteStatus ( ConstUtil.MATERIAL_STATUS_FINISH ) );
                                } );
                            }
                        }
                    }
                }
            } );
        }
    }

    /**
     * todo 销售合同是普通合同类型
     * @param materialDetailEntity
     * @param contractSaleEntity
     */
    private void checkOrdinaryContract (MaterialDetailEntity materialDetailEntity, ContractSaleEntity contractSaleEntity, List<MaterialDetailEntity> detailEntityList) {
        //获取选择销售合同的明细
        List<MaterialDetailEntity> list = detailEntityList.stream ()
                .filter ( s -> s.getSourceMaterialDetailId () != null && s.getRelationId () != null &&
                        s.getSourceMaterialDetailId ().equals ( materialDetailEntity.getSourceMaterialDetailId () ) &&
                        s.getRelationId ().equals ( materialDetailEntity.getRelationId () )
                )
                .collect ( Collectors.toList () );
        //过滤出还在执行中合同对应的物料明细
        List<MaterialDetailEntity> executeEntityList = list.stream ().filter ( s -> s.getExecuteStatus ().equals ( ConstUtil.MATERIAL_STATUS_EXECUTE ) ).collect ( Collectors.toList () );
        //计算出该合同下的该物料的总数量
        if ( CollectionUtils.isEmpty ( executeEntityList ) ) {
            throw new RuntimeException ( "该合同下没有该物料已关闭" );
        }
        //计算出该合同下的明细还在执行中的该物料的总数量
        double sum = executeEntityList.stream ().mapToDouble ( detail -> Double.parseDouble ( detail.getNumber () ) ).sum ();
        //计算合同中明细的金额总合
        BigDecimal totalAmount = list.stream ()
                .map ( MaterialDetailEntity :: getAmountMoney )
                .map ( BigDecimal :: new )
                .reduce ( BigDecimal.ZERO, BigDecimal :: add );
        //计算合同中还在执行中明细的金额总合
        BigDecimal executeAmount = executeEntityList.stream ()
                .map ( MaterialDetailEntity :: getAmountMoney )
                .map ( BigDecimal :: new )
                .reduce ( BigDecimal.ZERO, BigDecimal :: add );
        double excuteNum = 0;
        //合同中已经执行过的金额
        BigDecimal finshTotalAmount = new BigDecimal ( "0.00" );
        if ( sum < Double.parseDouble ( materialDetailEntity.getNumber () ) ) {
            throw new RuntimeException ( "销售订单的数量超出了该合同下的数量" );
        }
        //声明明细对应金额
        BigDecimal amountMoney = new BigDecimal ( "0.00" );
        if ( StringUtils.isNotEmpty ( materialDetailEntity.getAmountMoney () ) ) {
            amountMoney = new BigDecimal ( materialDetailEntity.getAmountMoney () );
        }
        if ( executeAmount.compareTo ( amountMoney ) == - 1 ) {
            throw new RuntimeException ( "销售订单的金额超出了该合同下的金额" );
        }
        //查询该合同下的所有销售订单
        List<ContractOrderEntity> contractOrderEntities = contractOrderService.list ( new LambdaQueryWrapper<ContractOrderEntity> ()
                                                                                              .eq ( ContractOrderEntity :: getContractId, contractSaleEntity.getId () )
                                                                                              .eq ( ContractOrderEntity :: getSourceContractType, ConstUtil.ORDER_SALE_TYPE )
        );
        List<String> orderIds = contractOrderEntities.stream ().map ( s -> s.getOrderId () ).collect ( Collectors.toList () );
        List<MaterialDetailEntity> orderMaterialDetails = new ArrayList<> ();
        if ( ! CollectionUtils.isEmpty ( orderIds ) ) {
            //查询该合同下的所有已执行销售订单的该物料的数量&金额
            orderMaterialDetails = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ()
                                                                        .in ( "relation_id", orderIds )
                                                                        .eq ( "type", ConstUtil.ORDER_SALE )
                                                                        .eq ( "source_material_detail_id", materialDetailEntity.getSourceMaterialDetailId () ) );
            excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( detail -> Double.parseDouble ( detail.getNumber () ) ).sum ();
            finshTotalAmount = orderMaterialDetails.stream ()
                    .map ( MaterialDetailEntity :: getAmountMoney )
                    .map ( BigDecimal :: new )
                    .reduce ( BigDecimal.ZERO, BigDecimal :: add );
        }
        double surplusNum = sum - excuteNum;
        BigDecimal residueAmount = totalAmount.subtract ( finshTotalAmount );

        //如果该物料的数量等于该合同下的未执行物料的数量，则该物料的执行状态为已完成
        if ( surplusNum == Double.parseDouble ( materialDetailEntity.getNumber () ) && residueAmount.compareTo ( amountMoney ) == 0 ) {
            executeEntityList.forEach ( s -> {
                materialDetailService.updateById ( s.setExecuteStatus ( ConstUtil.MATERIAL_STATUS_FINISH ) );
            } );
            //合同里该物料明细的价税合计
            String contractTotalTaxPrice = executeEntityList.get ( 0 ).getTotalTaxPrice ();
            //该物料明细已经形成采购订单的价税合计
            BigDecimal orderTotalTaxPrice = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).map ( material -> new BigDecimal ( material.getTotalTaxPrice () ) ).reduce ( BigDecimal.ZERO, BigDecimal :: add );
            //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成采购订单的价税合计)
            BigDecimal surplusTotalTaxPrice = new BigDecimal ( contractTotalTaxPrice ).subtract ( orderTotalTaxPrice );
            //计算单价(剩余的价税合计 / 此次数量)
            BigDecimal price = surplusTotalTaxPrice.divide ( new BigDecimal ( materialDetailEntity.getNumber () ), BigDecimal.ROUND_HALF_UP );
            //将值赋值给原字段
            materialDetailEntity.setPrice ( String.valueOf ( price ) );
            materialDetailEntity.setTotalTaxPrice ( String.valueOf ( surplusTotalTaxPrice ) );
        }
        if ( Double.parseDouble ( materialDetailEntity.getNumber () ) > surplusNum ) {
            throw new RuntimeException ( "销售订单数量不能大于销售合同明细数量！" );
        }
        if ( residueAmount.compareTo ( amountMoney ) == - 1 ) {
            throw new RuntimeException ( "销售订单金额不能大于销售合同明细金额！" );
        }
    }

    /**
     * todo 销售合同是金额合同类型
     * @param materialDetailEntity
     * @param contractSaleEntity
     * @param detailEntityList     多合同所有合同的物料明细
     */
    private void checkAmountContract (MaterialDetailEntity materialDetailEntity, ContractSaleEntity contractSaleEntity, List<MaterialDetailEntity> detailEntityList) {
        //获取选择销售合同金额
        BigDecimal contractMoney = new BigDecimal ( contractSaleEntity.getMoney () );
        BigDecimal amountMoney = new BigDecimal ( materialDetailEntity.getAmountMoney () );
        if ( contractMoney.compareTo ( amountMoney ) == - 1 ) {
            throw new RuntimeException ( "销售订单的金额超出了该合同下的金额" );
        }
        //查询该合同下的所有销售订单
        List<ContractOrderEntity> contractOrderEntities = contractOrderService.list ( new LambdaQueryWrapper<ContractOrderEntity> ()
                                                                                              .eq ( ContractOrderEntity :: getContractId, contractSaleEntity.getId () )
                                                                                              .eq ( ContractOrderEntity :: getSourceContractType, ConstUtil.ORDER_SALE_TYPE )
        );
        List<String> orderIds = contractOrderEntities.stream ().map ( s -> s.getOrderId () ).collect ( Collectors.toList () );
        if ( ! CollectionUtils.isEmpty ( orderIds ) ) {
            //查询该合同下的所有已执行销售订单的该物料的数量&金额
            List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ().in ( "relation_id", orderIds ).eq ( "type", ConstUtil.ORDER_SALE ).eq ( "material_id", materialDetailEntity.getMaterialId () ) );
            //已经执行过订单明细的金额总合
            BigDecimal finshTotalAmount = orderMaterialDetails.stream ()
                    .map ( MaterialDetailEntity :: getAmountMoney )
                    .map ( BigDecimal :: new )
                    .reduce ( BigDecimal.ZERO, BigDecimal :: add );
            //合同中剩余的订单金额
            BigDecimal residueAmount = contractMoney.subtract ( finshTotalAmount );
            if ( residueAmount.compareTo ( amountMoney ) == - 1 ) {
                throw new RuntimeException ( "销售订单金额不能大于销售合同剩余金额！" );
            }
            if ( residueAmount.compareTo ( amountMoney ) == 0 ) {
                contractSaleEntity.setIsClose ( ConstUtil.CONTRACT_IS_CLOSE_YES );
                contractSaleService.updateById ( contractSaleEntity );
            }
        }

    }

    /**
     * 校验销售订单明细信息根据价目表
     * @param checkSaleMarkedPriceDto
     */
    public List<MaterialDetailEntity> checkSaleOrderDetailByPriceInfo (CheckSaleMarkedPriceDto checkSaleMarkedPriceDto) {
        List<MaterialDetailEntity> materialDetailEntities = checkSaleMarkedPriceDto.getMaterialDetailEntities ();
        SaleMarkedPriceEntity saleMarkedPriceEntity = markedPriceService.selectSaleMarkedPriceById ( checkSaleMarkedPriceDto.getPriceinfoId () );
        List<SaleMarkedCustomerEntity> customerEntities = saleMarkedPriceEntity.getSaleMarkedCustomerEntities ();
        List<String> customerCodes = customerEntities.stream ().filter ( s -> ConstUtil.SALE_PRICE_TYPE_CUSTOMER.equals ( s.getType () ) ).map ( s -> s.getCode () ).collect ( Collectors.toList () );
        List<String> saleCodes = customerEntities.stream ().filter ( s -> ConstUtil.SALE_PRICE_TYPE_SALE.equals ( s.getType () ) ).map ( s -> s.getCode () ).collect ( Collectors.toList () );
        List<SaleMakedDetailEntity> saleMakedDetailEntities = saleMarkedPriceEntity.getSaleMakedDetailEntities ();
        LocalDate currentDate = LocalDate.now ();
        List<MaterialDetailEntity> orderDetails = new ArrayList<> ();
        //选择的价目表没有适用客户也没有适用销售，针对所有，则校验金额不能比价目表最低价小
        if ( CollectionUtils.isEmpty ( customerCodes ) && CollectionUtils.isEmpty ( saleCodes ) ) {
            //价目对象是物料的
            if ( ConstUtil.SALE_PRICE_OBJECT_MATERIAL.equals ( saleMarkedPriceEntity.getPriceObject () ) ) {
                checkPriceByMaterialCode ( materialDetailEntities, saleMakedDetailEntities, currentDate, orderDetails );
            } else {//todo 选择的价目对象是物料分组

            }
        }
        //选择的价目表绑定了适用客户或者绑定了适用销售，销售订单里没有特殊的客户也没有特殊的销售，则校验不金额必须比价目表区间金额大
        if ( ! CollectionUtils.isEmpty ( customerCodes ) && ! CollectionUtils.isEmpty ( saleCodes ) && ! customerCodes.contains ( checkSaleMarkedPriceDto.getCustomerId () ) && ! saleCodes.contains ( checkSaleMarkedPriceDto.getSaleId () ) ) {
            System.out.println ( "选择了客户或者销售" );
        }
        //选择了价目表绑定了适用客户或者绑定了适用销售，销售订单里也有特殊的客户或者特殊的销售，则校验金额不能比价目表最低价小
        if ( ( ! CollectionUtils.isEmpty ( customerCodes ) && customerCodes.contains ( checkSaleMarkedPriceDto.getCustomerId () ) ) || ( ! CollectionUtils.isEmpty ( saleCodes ) && saleCodes.contains ( checkSaleMarkedPriceDto.getSaleId () ) ) ) {
            if ( ConstUtil.SALE_PRICE_OBJECT_MATERIAL.equals ( saleMarkedPriceEntity.getPriceObject () ) ) {
                checkPriceByMaterialCode ( materialDetailEntities, saleMakedDetailEntities, currentDate, orderDetails );
            } else {//todo 选择的价目对象是物料分组

            }
        }
        return orderDetails;
    }

    /**
     * 根据物料查询销售订单变更
     * @param queryDto
     * @return
     */
    @Override
    public IPage<SaleOrderChangeVo> selectSaleOrderChangeListByMaterial (SaleOrderQueryDto queryDto) {
        return materialDetailService.selectSaleOrderChangeListByMaterial ( queryDto );
    }

    /**
     * 选择的价目表价目对象是物料
     * @param materialDetailEntities
     * @param saleMakedDetailEntities
     * @param currentDate
     */
    private void checkPriceByMaterialCode (List<MaterialDetailEntity> materialDetailEntities, List<SaleMakedDetailEntity> saleMakedDetailEntities, LocalDate currentDate, List<MaterialDetailEntity> orderDetails) {
        for ( MaterialDetailEntity s : materialDetailEntities ) {
            List<SaleMakedDetailEntity> detailEntities = saleMakedDetailEntities.stream ().filter ( m -> m.getCode ().equals ( s.getMaterialCode () ) && m.getLineState ().equals ( ConstUtil.STATE_FINISH ) ).collect ( Collectors.toList () );
            SaleMakedDetailEntity detailEntity = detailEntities.stream ()
                    .filter ( entity ->
                                      dateToLocalDate ( entity.getExpirationDate () ).isAfter ( currentDate.minusDays ( 1 ) ) &&
                                              dateToLocalDate ( entity.getLoseDate () ).isBefore ( currentDate.plusDays ( 1 ) )
                    ).findFirst ().orElse ( null );
            if ( Objects.isNull ( detailEntity ) ) {
                break;
            } else {
                //过滤起始数量或者最大数量不为null的数据
                //如果起始数量和最大数量没有填，那就是针对物料控制价格
                if ( StringUtils.isEmpty ( detailEntity.getStartNum () ) && StringUtils.isEmpty ( detailEntity.getEndNum () ) ) {
                    BigDecimal bigDecimalTaxPrice = new BigDecimal ( s.getTaxPrice () );
                    checkPrice ( detailEntity, bigDecimalTaxPrice, s, orderDetails );

                } else {//如果数量有区间，就是根据区间去控制的价格，就是双控制。
                    /**
                     * todo 数量有区间分三种情况
                     * 1.startNum,endNum都不为null;
                     * 2.可能startNum为null,endNum不为null;
                     * 3.可能startNum不为null,endNum为null;
                     */
                    BigDecimal number = new BigDecimal ( s.getNumber () );
                    BigDecimal taxPrice = new BigDecimal ( s.getTaxPrice () );
                    BigDecimal startNum = detailEntity.getStartNum () != null ? new BigDecimal ( detailEntity.getStartNum () ) : BigDecimal.ZERO;
                    BigDecimal endNum = detailEntity.getEndNum () != null ? new BigDecimal ( detailEntity.getEndNum () ) : BigDecimal.ZERO;
                    if ( startNum.compareTo ( endNum ) > 0 ) {
                        throw new RuntimeException ( "价目表的开始数量不能大于结束数量" );
                    }
                    checkPriceInRange ( detailEntity, taxPrice, number, startNum, endNum, s, orderDetails );
                            /*if (StringUtils.isNotEmpty(detailEntity.getStartNum()) && StringUtils.isNotEmpty(detailEntity.getEndNum())){
                                //如果startNum和endNum都有值，则判断s中的数量在startNum和endNum之间
                                BigDecimal bigDecimalTaxPrice = new BigDecimal(s.getTaxPrice());
                                BigDecimal number = new BigDecimal(s.getNumber());
                                if (number.compareTo(new BigDecimal(detailEntity.getStartNum())) >= 0 && number.compareTo(new BigDecimal(detailEntity.getEndNum())) <= 0){
                                    checkPrice(detailEntity, bigDecimalTaxPrice);
                                }else{
                                    throw new RuntimeException("销售订单数量要在价目表规定的数量范围！");
                                }
                            }
                            if (StringUtils.isEmpty(detailEntity.getStartNum()) && StringUtils.isNotEmpty(detailEntity.getEndNum())){
                                //如果startNum为null,endNum不为null，则判断s中的数量小于endNum
                                BigDecimal bigDecimalTaxPrice = new BigDecimal(s.getTaxPrice());
                                BigDecimal number = new BigDecimal(s.getNumber());
                                if (number.compareTo(new BigDecimal(detailEntity.getEndNum())) <= 0){
                                    checkPrice(detailEntity, bigDecimalTaxPrice);
                                }else{
                                    throw new RuntimeException("销售订单数量不能大于价目表规定的数量范围！");
                                }
                            }
                            if (StringUtils.isNotEmpty(detailEntity.getStartNum()) && StringUtils.isEmpty(detailEntity.getEndNum())){
                                //如果startNum不为null,endNum为null，则判断s中的数量大于startNum
                                BigDecimal bigDecimalTaxPrice = new BigDecimal(s.getTaxPrice());
                                BigDecimal number = new BigDecimal(s.getNumber());
                                if (number.compareTo(new BigDecimal(detailEntity.getStartNum())) >= 0){
                                    checkPrice(detailEntity, bigDecimalTaxPrice);
                                }else{
                                    throw new RuntimeException("销售订单数量不能小于价目表规定的数量范围！");
                                }
                            }*/
                }
            }

        }

    }

    /**
     * 价目金额可能区间分三种情况
     * 1.startPrice,endPrice都不为null;
     * 2.可能startPrice为null,endPrice不为null;
     * 3.可能startPrice不为null,endPrice为null;
     * @param detailEntity
     * @param bigDecimalTaxPrice
     */
    private void checkPrice (SaleMakedDetailEntity detailEntity, BigDecimal bigDecimalTaxPrice, MaterialDetailEntity materialDetail, List<MaterialDetailEntity> orderDetails) {

        BigDecimal startPrice = detailEntity.getStartPrice () != null ? new BigDecimal ( detailEntity.getStartPrice () ) : BigDecimal.ZERO;
        BigDecimal endPrice = detailEntity.getEndPrice () != null ? new BigDecimal ( detailEntity.getEndPrice () ) : BigDecimal.ZERO;

        boolean isPriceInRange =
                ( startPrice.compareTo ( endPrice ) <= 0 && bigDecimalTaxPrice.compareTo ( startPrice ) >= 0 && bigDecimalTaxPrice.compareTo ( endPrice ) <= 0 ) ||
                        ( startPrice.compareTo ( endPrice ) > 0 && ( bigDecimalTaxPrice.compareTo ( startPrice ) >= 0 || bigDecimalTaxPrice.compareTo ( endPrice ) <= 0 ) );

        if ( ! isPriceInRange ) {
            orderDetails.add ( materialDetail );
            String errorMessage = detailEntity.getStartPrice () != null && detailEntity.getEndPrice () != null ?
                    "销售订单金额要在价目表规定的价格范围！" :
                    detailEntity.getStartPrice () != null ?
                            "销售订单金额不能小于价目表规定的价格范围！" :
                            "销售订单金额不能大于价目表规定的价格范围！";
            System.out.println ( "需要审核的明细======>{" + materialDetail.getMaterialCode () + "," + "}" );
            System.out.println ( "错误信息=========>" + errorMessage );
//            throw new RuntimeException(errorMessage);
        }

    }

    /**
     * 根据数量判断是否在区间内
     * @param detailEntity
     * @param taxPrice
     * @param number
     * @param startNum
     * @param endNum
     */
    private void checkPriceInRange (SaleMakedDetailEntity detailEntity, BigDecimal taxPrice, BigDecimal number,
                                    BigDecimal startNum, BigDecimal endNum, MaterialDetailEntity materialDetail, List<MaterialDetailEntity> orderDetails) {
        // 使用统一的异常类型，并提供更详细的错误信息
        if ( ( StringUtils.isNotEmpty ( detailEntity.getStartNum () ) && StringUtils.isNotEmpty ( detailEntity.getEndNum () ) )
                && ( number.compareTo ( startNum ) >= 0 && number.compareTo ( endNum ) <= 0 ) ) {
            checkPrice ( detailEntity, taxPrice, materialDetail, orderDetails );
        } else if ( StringUtils.isEmpty ( detailEntity.getStartNum () ) && number.compareTo ( endNum ) <= 0 ) {
            checkPrice ( detailEntity, taxPrice, materialDetail, orderDetails );
        } else if ( StringUtils.isEmpty ( detailEntity.getEndNum () ) && number.compareTo ( startNum ) >= 0 ) {
            checkPrice ( detailEntity, taxPrice, materialDetail, orderDetails );
        }
    }

    /**
     * 将Date转换为LocalDate
     * @param date
     * @return
     */
    private static LocalDate dateToLocalDate (Date date) {
        return date.toInstant ().atZone ( ZoneId.systemDefault () ).toLocalDate ();
    }

    /**
     * 修改销售订单
     * @param saleOrderAddDto 销售订单
     * @return 结果
     */
    @Override
    public AjaxResult updateSaleOrder (SaleOrderAddDto saleOrderAddDto) {
        SaleOrderEntity saleOrder = saleOrderAddDto.getSaleOrderEntity ();
        if ( StringUtils.isEmpty ( saleOrder.getParentId () ) ) {
            return AjaxResult.error ( "销售订单id为空！" );
        }
        //修改的原销售订单
        SaleOrderEntity parentOrder = this.getById ( saleOrder.getParentId () );
        if ( parentOrder.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "该销售订单已执行完成，不能修改！" );
        }
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        Date nowDate = DateUtils.getNowDate ();
        saleOrder.setUpdateBy ( userId );
        saleOrder.setUpdateTime ( nowDate );
        saleOrder.setId ( parentOrder.getId () );
        saleOrder.setUpdateState ( ConstUtil.ORDER_IS_CHANGE_YES );
        boolean b = this.updateById ( saleOrder );
        if ( b ) {
            //新增销售订单变更单
            handleOrderByParentId ( parentOrder, saleOrder );
            //处理物料明细
            updateMaterialDetails ( saleOrderAddDto.getMaterialDetailEntities (), parentOrder.getId () );
            //处理销售订单条款
            updateOrderPurchaseTerms ( saleOrderAddDto.getOrderPurchaseTerms (), parentOrder.getId () );
            //处理物流跟踪
            updateSaleOrderLogistics ( saleOrderAddDto.getSaleOrderLogisticsEntities (), parentOrder.getId () );
            //处理销售订单收款计划
            updateSaleCollectionPlan ( saleOrderAddDto.getSaleCollectionPlanEntities (), parentOrder.getId () );
        }
        return AjaxResult.success ();
    }

    /**
     * 审核通过单据类型形成采购订单
     * @param saleOrderEntity
     * @return
     */
    @Override
    public boolean approvedSaleOrder (SaleOrderEntity saleOrderEntity) {
        if ( StringUtils.isNotEmpty ( saleOrderEntity.getKingDocCode () ) ) {
            //直运订单
            if ( ConstUtil.SALE_DOC_TYPE_DIRECT.equals ( saleOrderEntity.getKingDocCode () ) ) {
                List<MaterialDetailEntity> detailEntityList = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                                   .eq ( MaterialDetailEntity :: getRelationId, saleOrderEntity.getId () )
                                                                                                   .eq ( MaterialDetailEntity :: getType, ConstUtil.ORDER_SALE )
                );
                BigDecimal num = detailEntityList.stream ().map ( MaterialDetailEntity :: getNumber ).map ( BigDecimal :: new )
                        .reduce ( BigDecimal.ZERO, BigDecimal :: add );
                OrderEntity orderEntity = new OrderEntity ();
                orderEntity.setPurchaseOrg ( saleOrderEntity.getSaleGroup () );
                orderEntity.setPurchaseDept ( saleOrderEntity.getSaleDept () );
                orderEntity.setApplyId ( saleOrderEntity.getSaleId () );
                orderEntity.setSupplierId ( saleOrderEntity.getCustomerId () );
                orderEntity.setApplyTime ( saleOrderEntity.getCreateTime () );
                orderEntity.setSourceDocType ( String.valueOf ( ConstUtil.ORDER_SALE ) );
                orderEntity.setOrderNumber ( String.valueOf ( num ) );
                orderEntity.setOrderDetails ( detailEntityList );
                orderService.saveOrder ( orderEntity );

            }
            //todo 分销购销订单 当A系统里面的这笔销售订单生成出库单并审核后，自动生成B系统入库单（单据状态为已审核）
            //当在A系统中录入，销售订单（类型：分销购销订单），客户是：安徽烈阳，该销售订单审核后，
            // 会同时在B系统自动生成采购订单（类型：分销购销采购订单）供应商为：合肥烈阳，里面的物料明细，数量 金额等都保持一致（单据状态为已审核）。
            if ( ConstUtil.SALE_DOC_TYPE_DISTRIBUTION.equals ( saleOrderEntity.getKingDocCode () ) ) {
                List<MaterialDetailEntity> detailEntityList = materialDetailService.list ( new LambdaQueryWrapper<MaterialDetailEntity> ()
                                                                                                   .eq ( MaterialDetailEntity :: getRelationId, saleOrderEntity.getId () )
                                                                                                   .eq ( MaterialDetailEntity :: getType, ConstUtil.ORDER_SALE )
                );
                BigDecimal num = detailEntityList.stream ().map ( MaterialDetailEntity :: getNumber ).map ( BigDecimal :: new )
                        .reduce ( BigDecimal.ZERO, BigDecimal :: add );
                List<SysDept> sysDeptList = sysDeptService.list ( new LambdaQueryWrapper<SysDept> ()
                                                                          .eq ( SysDept :: getLevel, 1 )
                                                                          .eq ( SysDept :: getDelFlag, "0" )
                );
                List<String> deptIds = sysDeptList.stream ().map ( SysDept :: getDeptId ).collect ( Collectors.toList () );
                if ( deptIds.contains ( saleOrderEntity.getCustomerId () ) ) {
                    OrderEntity orderEntity = new OrderEntity ();
                    orderEntity.setDocType ( "4" );
                    orderEntity.setSupplierId ( saleOrderEntity.getSaleGroup () );
                    orderEntity.setApplyTime ( saleOrderEntity.getCreateTime () );
                    orderEntity.setSourceDocType ( String.valueOf ( ConstUtil.ORDER_SALE ) );
                    orderEntity.setOrderNumber ( String.valueOf ( num ) );
                    orderEntity.setOrderDetails ( detailEntityList );
                    orderService.saveOrder ( orderEntity );
                }
            }
        }
        boolean b = this.updateById ( saleOrderEntity );
        if ( b ) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 生成变更单
     * @param parentOrder 老销售订单数据
     * @param order       新销售订单数据
     */
    private void handleOrderByParentId (SaleOrderEntity parentOrder, SaleOrderEntity order) {
        if ( Objects.nonNull ( parentOrder ) && Objects.nonNull ( order ) ) {
            String newOrderId = SnowflakeIdWorker.getInstance ().nextStringId ();
            String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
            Date nowDate = DateUtils.getNowDate ();
            int count = this.count ( new LambdaQueryWrapper<SaleOrderEntity> ().eq ( SaleOrderEntity :: getParentId, parentOrder.getId () ) );
            //处理新变更单的单据编号
            String parentOrderNumber = parentOrder.getSaleCode ();
            String countStr = String.format ( "%04d", count );
            String newOrderNumber = parentOrderNumber.concat ( "_V" ).concat ( countStr );
            order.setId ( newOrderId );
            order.setSaleCode ( newOrderNumber );
            order.setParentId ( parentOrder.getId () );
            order.setOriginalOrderCode ( parentOrder.getSaleCode () );
            order.setCreateBy ( userId );
            order.setCreateTime ( nowDate );
            order.setSourceDocType ( ConstUtil.SALE_DOC_TYPE_CHANGE );
            order.setUpdateState ( ConstUtil.ORDER_IS_CHANGE_NO );
            boolean save = this.save ( order );
            List<MaterialDetailEntity> materialDetailList = order.getMaterialDetailEntities ();
            if ( save ) {
                if ( ! materialDetailList.isEmpty () ) {
                    materialDetailList.forEach ( s -> {
                        s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                        s.setRelationId ( newOrderId );
                        s.setType ( ConstUtil.ORDER_SALE_CHANGE_TYPE );
                        s.setCreateTime ( nowDate );
                        boolean materialDetailFlag = materialDetailService.save ( s );
                        if ( materialDetailFlag ) {
                            if ( Objects.nonNull ( s.getSaleOrderDelivery () ) ) {
                                SaleOrderDeliveryEntity saleOrderDelivery = s.getSaleOrderDelivery ();
                                String orderDeliveryId = SnowflakeIdWorker.getInstance ().nextStringId ();
                                saleOrderDelivery.setId ( orderDeliveryId );
                                saleOrderDelivery.setMaterialCode ( s.getMaterialCode () );
                                saleOrderDelivery.setOrderId ( newOrderId );
                                saleOrderDelivery.setCreateBy ( userId );
                                saleOrderDelivery.setCreateTime ( nowDate );
                                boolean orderDeliveryFlag = saleOrderDeliveryService.save ( saleOrderDelivery );
                                if ( orderDeliveryFlag ) {
                                    if ( ! CollectionUtils.isEmpty ( saleOrderDelivery.getSaleOrderDeliveryDetailEntities () ) ) {
                                        saleOrderDelivery.getSaleOrderDeliveryDetailEntities ().forEach ( saleDelivery -> {
                                            saleDelivery.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                                            saleDelivery.setDeliveryId ( orderDeliveryId );
                                            saleDelivery.setCreateBy ( userId );
                                            boolean saved = saleOrderDeliveryDetailService.save ( saleDelivery );
                                            if ( ! saved ) {
                                                throw new RuntimeException ( "订单发货明细保存失败！" );
                                            }
                                        } );
                                    }
                                }
                            }
                        }
                    } );
                }
            }

        }
    }

    /**
     * 批量删除销售订单
     * @param ids 需要删除的销售订单ID
     * @return 结果
     */
    @Override
    public int deleteSaleOrderByIds (String[] ids) {
        return saleOrderMapper.deleteSaleOrderByIds ( ids );
    }

    /**
     * 删除销售订单信息
     * @param id 销售订单ID
     * @return 结果
     */
    @Override
    public int deleteSaleOrderById (String id) {
        return saleOrderMapper.deleteSaleOrderById ( id );
    }

    /**
     * 新增销售合同界面，听过选销售订单查询销售合同的物料明细列表
     * @return
     * @author：Wuzh
     */
    @Override
    public List<ContractOrderMaterialDetailVo> queryMaterial () {
        List<ContractOrderMaterialDetailVo> contractOrderMaterialDetailVos = saleOrderMapper.queryMaterial ( ConstUtil.ORDER_SALE );
        return contractOrderMaterialDetailVos;
    }

    /**
     * 修改物料明细
     * @param newMaterials
     * @param orderId
     */
    private void updateMaterialDetails (List<MaterialDetailEntity> newMaterials, String orderId) {
        Date changeTime = DateUtils.getNowDate ();
        if ( ! CollectionUtils.isEmpty ( newMaterials ) ) {
            List<MaterialDetailEntity> materialDetails = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ().eq ( "relation_id", orderId ).eq ( "type", ConstUtil.ORDER_SALE ) );
            for ( MaterialDetailEntity materialDetail : materialDetails ) {
                boolean found = newMaterials.stream ().anyMatch ( d -> Objects.equals ( d.getId (), materialDetail.getId () ) );
                if ( ! found ) {
                    materialDetailService.removeById ( materialDetail.getId () );
                }
            }
            newMaterials.stream ().forEach ( materialDetail -> {
                if ( Objects.nonNull ( materialDetail.getId () ) ) {
                    materialDetail.setChangeTime ( changeTime );
                    boolean updated = materialDetailService.updateById ( materialDetail );
                    if ( ! updated ) {
                        throw new RuntimeException ( "变更销售订单物料明细失败！" );
                    }
                } else {
                    materialDetail.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                    materialDetail.setRelationId ( orderId );
                    materialDetail.setType ( ConstUtil.ORDER_SALE );
                    materialDetail.setCreateTime ( changeTime );
                    boolean save = materialDetailService.save ( materialDetail );
                    if ( ! save ) {
                        throw new RuntimeException ( "变更销售订单物料明细失败！" );
                    }
                }
                //变更物料明细交货安排信息
                updateOrderDeliverys ( materialDetail.getSaleOrderDelivery (), orderId, materialDetail.getMaterialCode () );

            } );
        }
    }

    /**
     * 销售条款
     * @param orderPurchaseTermsEntities
     * @param orderId
     */
    private void updateOrderPurchaseTerms (List<OrderPurchaseTermsEntity> orderPurchaseTermsEntities, String orderId) {
        orderPurchaseTermsService.remove ( new LambdaQueryWrapper<> ( OrderPurchaseTermsEntity.class )
                                                   .eq ( OrderPurchaseTermsEntity :: getOrderId, orderId )
                                                   .eq ( OrderPurchaseTermsEntity :: getType, ConstUtil.SALE_ORDER_TYPE_TERMS )
        );
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        Date nowDate = DateUtils.getNowDate ();
        for ( OrderPurchaseTermsEntity orderPurchaseTerm : orderPurchaseTermsEntities ) {
            orderPurchaseTerm.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
            orderPurchaseTerm.setOrderId ( orderId );
            orderPurchaseTerm.setCreateTime ( nowDate );
            orderPurchaseTerm.setUserId ( userId );
            orderPurchaseTerm.setType ( ConstUtil.SALE_ORDER_TYPE_TERMS );
        }
        boolean saved = orderPurchaseTermsService.saveBatch ( orderPurchaseTermsEntities );
        if ( ! saved ) {
            throw new RuntimeException ( "销售条款关联信息保存失败！" );
        }
    }

    /**
     * 修改物流信息
     * @param newSaleOrderLogistics
     * @param orderId
     */
    private void updateSaleOrderLogistics (List<SaleOrderLogisticsEntity> newSaleOrderLogistics, String orderId) {
        saleOrderLogisticsService.remove ( new LambdaQueryWrapper<> ( SaleOrderLogisticsEntity.class )
                                                   .eq ( SaleOrderLogisticsEntity :: getOrderId, orderId )
        );
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        Date nowDate = DateUtils.getNowDate ();
        newSaleOrderLogistics.forEach ( saleOrderLogistics -> {
            saleOrderLogistics.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
            saleOrderLogistics.setOrderId ( orderId );
            saleOrderLogistics.setCreateTime ( nowDate );
            saleOrderLogistics.setCreateBy ( userId );
        } );
        boolean saved = saleOrderLogisticsService.saveBatch ( newSaleOrderLogistics );
        if ( ! saved ) {
            throw new RuntimeException ( "物流信息保存失败！" );
        }
    }

    /**
     * 修改收款计划
     * @param saleCollectionPlanEntities
     * @param orderId
     */
    private void updateSaleCollectionPlan (List<SaleCollectionPlanEntity> saleCollectionPlanEntities, String orderId) {
        saleCollectionPlanService.remove ( new LambdaQueryWrapper<> ( SaleCollectionPlanEntity.class )
                                                   .eq ( SaleCollectionPlanEntity :: getOrderId, orderId )
        );
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        Date nowDate = DateUtils.getNowDate ();
        saleCollectionPlanEntities.forEach ( saleCollectionPlan -> {
            saleCollectionPlan.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
            saleCollectionPlan.setOrderId ( orderId );
            saleCollectionPlan.setCreateTime ( nowDate );
            saleCollectionPlan.setCreateBy ( userId );
        } );
        boolean saved = saleCollectionPlanService.saveBatch ( saleCollectionPlanEntities );
        if ( ! saved ) {
            throw new RuntimeException ( "销售收款计划保存失败！" );
        }
    }

    /**
     * 修改物料明细的交货安排信息
     * @param newOrderDelivery
     * @param orderId
     * @param materialCode
     */
    private void updateOrderDeliverys (SaleOrderDeliveryEntity newOrderDelivery, String orderId, String materialCode) {
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        Date nowDate = DateUtils.getNowDate ();
        if ( Objects.nonNull ( newOrderDelivery ) ) {
            List<SaleOrderDeliveryEntity> deliveryList = saleOrderDeliveryService.list ( new LambdaQueryWrapper<SaleOrderDeliveryEntity> ().eq ( SaleOrderDeliveryEntity :: getOrderId, orderId ).eq ( SaleOrderDeliveryEntity :: getMaterialCode, materialCode ) );
            if ( ! CollectionUtils.isEmpty ( deliveryList ) ) {
                List<String> deliveryIdList = deliveryList.stream ().filter ( Objects :: nonNull ).map ( SaleOrderDeliveryEntity :: getId ).collect ( Collectors.toList () );
                saleOrderDeliveryDetailService.remove ( new LambdaQueryWrapper<SaleOrderDeliveryDetailEntity> ().in ( SaleOrderDeliveryDetailEntity :: getDeliveryId, deliveryIdList ) );
                saleOrderDeliveryService.removeByIds ( deliveryIdList );
            }
            String orderDeliveryId = SnowflakeIdWorker.getInstance ().nextStringId ();
            newOrderDelivery.setId ( orderDeliveryId );
            newOrderDelivery.setOrderId ( orderId );
            newOrderDelivery.setCreateBy ( userId );
            newOrderDelivery.setCreateTime ( nowDate );
            boolean save = saleOrderDeliveryService.save ( newOrderDelivery );
            if ( save ) {
                if ( ! CollectionUtils.isEmpty ( newOrderDelivery.getSaleOrderDeliveryDetailEntities () ) ) {
                    List<SaleOrderDeliveryDetailEntity> deliveryDetailEntities = newOrderDelivery.getSaleOrderDeliveryDetailEntities ();
                    for ( SaleOrderDeliveryDetailEntity orderDeliveryDetail : deliveryDetailEntities ) {
                        orderDeliveryDetail.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                        orderDeliveryDetail.setDeliveryId ( orderDeliveryId );
                        orderDeliveryDetail.setCreateBy ( userId );
                        orderDeliveryDetail.setCreateTime ( nowDate );
                        boolean detailSave = saleOrderDeliveryDetailService.save ( orderDeliveryDetail );
                        if ( ! detailSave ) {
                            throw new RuntimeException ( "变更销售订单交货安排明细信息失败！" );
                        }
                    }
                }
            } else {
                throw new RuntimeException ( "变更销售订单交货安排信息失败！" );
            }
        }
    }


    /**
     * 暂存修改销售订单
     * @param
     */
    private boolean updateDraftSaleOrder (SaleOrderAddDto saleOrderAddDto) {
        SaleOrderEntity saleOrderEntity = saleOrderAddDto.getSaleOrderEntity ();
        this.removeBySaleOrderId ( saleOrderEntity.getId () );
        this.saveDraftSaleOrderDetail ( saleOrderAddDto );
        return this.updateById ( saleOrderEntity );
    }

    private void saveDraftSaleOrderDetail (SaleOrderAddDto saleOrderAddDto) {
        SaleOrderEntity saleOrderEntity = saleOrderAddDto.getSaleOrderEntity ();
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getOrderPurchaseTerms () ) ) {
            saleOrderAddDto.getOrderPurchaseTerms ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setCreateTime ( saleOrderEntity.getCreateTime () );
                s.setType ( ConstUtil.SALE_ORDER_TYPE_TERMS );
                s.setOrderId ( saleOrderEntity.getId () );
            } );
            if ( ! orderPurchaseTermsService.saveBatch ( saleOrderAddDto.getOrderPurchaseTerms () ) ) {
                throw new RuntimeException ( "暂存失败" );
            }
        }
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getSaleOrderLogisticsEntities () ) ) {
            saleOrderAddDto.getSaleOrderLogisticsEntities ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setCreateTime ( saleOrderEntity.getCreateTime () );
                s.setOrderId ( saleOrderEntity.getId () );
            } );
            boolean b = saleOrderLogisticsService.saveBatch ( saleOrderAddDto.getSaleOrderLogisticsEntities () );
            if ( ! b ) {
                throw new RuntimeException ( "暂存销售订单物流信息失败" );
            }
        }
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getSaleCollectionPlanEntities () ) ) {
            saleOrderAddDto.getSaleCollectionPlanEntities ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setOrderId ( saleOrderEntity.getId () );
                s.setCreateTime ( saleOrderEntity.getCreateTime () );
            } );
            boolean saveBatch = saleCollectionPlanService.saveBatch ( saleOrderAddDto.getSaleCollectionPlanEntities () );
            if ( ! saveBatch ) {
                throw new RuntimeException ( "暂存销售订单收款计划失败" );
            }
        }
        if ( ! CollectionUtils.isEmpty ( saleOrderAddDto.getMaterialDetailEntities () ) ) {
            saleOrderAddDto.getMaterialDetailEntities ().forEach ( s -> {
                s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                s.setCreateTime ( saleOrderEntity.getCreateTime () );
                s.setState ( ConstUtil.STATE_IN_DRAFT );
                s.setRelationId ( saleOrderEntity.getId () );
                s.setType ( ConstUtil.ORDER_SALE );
            } );
            boolean b = materialDetailService.saveBatch ( saleOrderAddDto.getMaterialDetailEntities () );
            if ( ! b ) {
                throw new RuntimeException ( "暂存销售订单明细失败" );
            }
            for ( MaterialDetailEntity materialDetailEntity : saleOrderAddDto.getMaterialDetailEntities () ) {
                //销售订单交货计划明细
                SaleOrderDeliveryEntity saleOrderDeliveryEntity = materialDetailEntity.getSaleOrderDelivery ();
                if ( ! Objects.isNull ( saleOrderDeliveryEntity ) ) {
                    String deliverId = SnowflakeIdWorker.getInstance ().nextStringId ();
                    saleOrderDeliveryEntity.setId ( deliverId );
                    saleOrderDeliveryEntity.setOrderId ( saleOrderEntity.getId () );
                    saleOrderDeliveryEntity.setCreateTime ( saleOrderEntity.getCreateTime () );
                    boolean saved = saleOrderDeliveryService.save ( saleOrderDeliveryEntity );
                    if ( ! saved ) {
                        throw new RuntimeException ( "暂存交货明细基础信息失败" );
                    }
                    if ( ! CollectionUtils.isEmpty ( saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities () ) ) {
                        saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities ().forEach ( s -> {
                            s.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                            s.setOrderId ( saleOrderEntity.getId () );
                            s.setDeliveryId ( deliverId );
                            s.setCreateTime ( saleOrderEntity.getCreateTime () );
                        } );
                        boolean saveBatch = saleOrderDeliveryDetailService.saveBatch ( saleOrderDeliveryEntity.getSaleOrderDeliveryDetailEntities () );
                        if ( ! saveBatch ) {
                            throw new RuntimeException ( "暂存交货明细详情信息失败" );
                        }
                    }
                }
            }
        }
    }


    private void removeBySaleOrderId (String saleOrderId) {
        saleOrderDeliveryService.remove ( new LambdaQueryWrapper<> ( SaleOrderDeliveryEntity.class ).eq ( SaleOrderDeliveryEntity :: getOrderId, saleOrderId ) );
        saleOrderDeliveryDetailService.remove ( new LambdaQueryWrapper<> ( SaleOrderDeliveryDetailEntity.class ).eq ( SaleOrderDeliveryDetailEntity :: getOrderId, saleOrderId ) );
        saleOrderLogisticsService.remove ( new LambdaQueryWrapper<> ( SaleOrderLogisticsEntity.class ).eq ( SaleOrderLogisticsEntity :: getOrderId, saleOrderId ) );
        saleCollectionPlanService.remove ( new LambdaQueryWrapper<> ( SaleCollectionPlanEntity.class ).eq ( SaleCollectionPlanEntity :: getOrderId, saleOrderId ) );
        orderPurchaseTermsService.remove ( new LambdaQueryWrapper<> ( OrderPurchaseTermsEntity.class ).eq ( OrderPurchaseTermsEntity :: getOrderId, saleOrderId ) );
        materialDetailService.remove ( new LambdaQueryWrapper<> ( MaterialDetailEntity.class ).eq ( MaterialDetailEntity :: getRelationId, saleOrderId ) );
    }


    @Override
    public AjaxResult queryOrderDetailList (SaleOrderQueryDto saleOrderQueryDto) {
        QueryWrapper<SaleOrderEntity> saleOrderEntityQueryWrapper = baseQuery ( saleOrderQueryDto );
        List<SaleOrderEntity> list = this.list ( saleOrderEntityQueryWrapper );
        if ( ! CollectionUtils.isEmpty ( list ) ) {
            list.forEach ( s -> {
                KingDocTypeEntity one = kingDocTypeEntityService.getOne ( new LambdaQueryWrapper<KingDocTypeEntity> ().eq ( KingDocTypeEntity :: getDocCode, s.getSourceDocType () ) );
                if ( Objects.nonNull ( one ) ) {
                    s.setSourceDocType ( one.getTitle () );
                }
                if ( StringUtils.isNotEmpty ( s.getCustomerId () ) ) {
                    CustomerEntity customerEntity = customerInfoService.getById ( s.getCustomerId () );
                    s.setCustomerName ( customerEntity.getCustomerName () );
                }
                //物料明细
                List<MaterialDetailEntity> materialDetails = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ().eq ( "relation_id", s.getId () ).eq ( "type", ConstUtil.ORDER_SALE ) );
                if ( ! CollectionUtils.isEmpty ( materialDetails ) ) {
                    materialDetails.forEach ( materialDetail -> {
                        MaterialEntity materialEntity = new MaterialEntity ();
                        if ( StringUtils.isEmpty ( materialDetail.getMaterialId () ) ) {
                            materialEntity = materialInfoService.getOne ( new LambdaQueryWrapper<MaterialEntity> ().eq ( MaterialEntity :: getMaterialCode, materialDetail.getMaterialCode () ) );
                        } else {
                            materialEntity = materialInfoService.getById ( materialDetail.getMaterialId () );
                        }
                        Optional.ofNullable ( materialEntity ).ifPresent ( material -> {
                            materialDetail.setMaterial ( material );
                        } );
                    } );
                    s.setMaterialDetailEntities ( materialDetails );
                }
            } );
        }
        Page<SaleOrderEntity> page = new Page<> ( saleOrderQueryDto.getCurrent (), saleOrderQueryDto.getSize () );
        return AjaxResult.success ( ReturnPage.getReturnPage ( page, list ) );
    }

    private QueryWrapper<SaleOrderEntity> baseQuery (SaleOrderQueryDto saleOrderQueryDto) {
        QueryWrapper<SaleOrderEntity> query = Wrappers.query ();
        if ( ! StringUtils.isEmpty ( saleOrderQueryDto.getContractName () ) ) {
            List<ContractSaleEntity> contractSaleEntities = contractSaleService.list ( new LambdaQueryWrapper<ContractSaleEntity> ().like ( ContractSaleEntity :: getContractName, saleOrderQueryDto.getContractName () ) );
            if ( ! CollectionUtils.isEmpty ( contractSaleEntities ) ) {
                List<String> contractIds = contractSaleEntities.stream ().map ( s -> s.getId () ).collect ( Collectors.toList () );
                List<ContractOrderEntity> contractOrderEntities = contractOrderService.list ( new LambdaQueryWrapper<ContractOrderEntity> ().in ( ContractOrderEntity :: getContractId, contractIds ) );
                if ( ! CollectionUtils.isEmpty ( contractOrderEntities ) ) {
                    List<String> orderIds = contractOrderEntities.stream ().map ( s -> s.getOrderId () ).collect ( Collectors.toList () );
                    query.in ( "id", orderIds );
                }
            }
        }
        if ( StringUtils.isNotEmpty ( saleOrderQueryDto.getSaleCode () ) ) {
            query.eq ( "sale_code", saleOrderQueryDto.getSaleCode () );
        }
        if ( StringUtils.isNotEmpty ( saleOrderQueryDto.getSourceDocType () ) ) {
            query.eq ( "source_doc_type", saleOrderQueryDto.getSourceDocType () );
        }
        if ( StringUtils.isNotEmpty ( saleOrderQueryDto.getSaleDept () ) ) {
            query.eq ( "sale_dept", saleOrderQueryDto.getSaleDept () );
        }
        return query;
    }

    public static void main (String[] args) {
        BigDecimal num1 = new BigDecimal ( "3.32" );
        BigDecimal num2 = new BigDecimal ( "3.33" );
        int i = num2.compareTo ( num1 );
        System.out.println ( i );
    }

}
